/*
Copyright (C) 1997-2001 Id Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

//
// cg_local.h
// CGame local header
//

#ifndef __CGAME_LOCAL_H__
#define __CGAME_LOCAL_H__

#include "../shared/shared.h"
#include "cg_shared.h"
#include "cg_api.h"
#include "cg_entities.h"
#include "cg_effects.h"
#include "cg_keys.h"
#include "cg_media.h"
#include "ui/ui_local.h"
#include "menu/menu.h"

extern cgImportAPI_t cgi;

// Local tags
enum {
	CGTAG_ANY,
	CGTAG_LOCATION,
	CGTAG_MAPFX,
	CGTAG_MENU,
};

// Generic memory allocation
#define CG_AllocA(size)					_alloca((size))

#define CG_MemAlloc(size)				cgi.Mem_Alloc((size),CGTAG_ANY,__FILE__,__LINE__)
#define CG_MemFree(ptr)					cgi.Mem_Free((ptr),__FILE__,__LINE__)
#define CG_StrDup(in)					cgi.Mem_StrDup((in),CGTAG_ANY,__FILE__,__LINE__)

// Allocates to a tagged location
// Useful for releasing entire blocks of memory at a time
#define CG_AllocTag(size,tag)			cgi.Mem_Alloc((size),(tag),__FILE__,__LINE__)
#define CG_FreeTag(tag)					cgi.Mem_FreeTag((tag),__FILE__,__LINE__)
#define CG_TagStrDup(in,tag)			cgi.Mem_StrDup((in),(tag),__FILE__,__LINE__)
#define CG_MemTagSize(tag)				cgi.Mem_TagSize((tag))
#define CG_ChangeTag(tagFrom,tagTo)		cgi.Mem_ChangeTag((tagFrom),(tagTo))

// Filesystem
#define CG_FS_FreeFile(buffer)			cgi.FS_FreeFile((buffer),__FILE__,__LINE__)

/*
=============================================================================

	CGAME STATE

=============================================================================
*/

enum {
	GAME_MOD_DEFAULT,
	GAME_MOD_DDAY,
	GAME_MOD_GIEX,
	GAME_MOD_LOX,
	GAME_MOD_ROGUE,
	GAME_MOD_XATRIX
};

struct clientInfo_t {
	char						name[MAX_CFGSTRLEN];
	char						cInfo[MAX_CFGSTRLEN];
	struct refMaterial_t		*skin;
	struct refMaterial_t		*icon;
	char						iconName[MAX_QPATH];
	struct refModel_t			*model;
	TList<struct refModel_t	*>	weaponModels;

	struct refModel_t			*ragdollPieces[RAG_COUNT];

	void Clear ()
	{
		weaponModels.Clear();
	}
};

struct cgPredictionState_t {
	float				step;						// for stair up smoothing
	uint32				stepTime;
	sint16				origins[CMD_BACKUP][3];		// for debug comparing against server
	vec3_t				origin;						// generated by CG_PredictMovement
	vec3_t				angles;
	vec3_t				velocity;
	vec3_t				error;
	int					viewHeight;
};

struct cgDownloadInfo_t {
	bool		downloading;

	char		*fileName;
	int			percent;
	float		bytesDown;
};

// ==========================================================================

struct cgState_t {
	byte				currGameMod;

	// Times
	// Note: there's a net and refresh time because they run asynchronously
	int					netTime;			// Net time
	float				netFrameTime;		// Network frame delta (scaled by timescale)

	int					refreshTime;		// Refresh time
	float				refreshFrameTime;	// Refresh frame delta (scaled by timescale)

	int					realTime;			// System time

	// View settings
	bool				bOldAreaBits;
	refDef_t			refDef;

	vec3_t				damageBlend;
	float				bonusAlpha, damageAlpha;
	colorf				viewBlend;

	// the client maintains its own idea of view angles, which are
	// sent to the server each frame. It is cleared to 0 upon entering each level.
	// the server sends a delta each frame which is added to the locally
	// tracked view angles to account for standing on rotating objects,
	// and teleport direction changes
	vec3_t				viewAngles;

	refConfig_t			refConfig;

	bool				forceRefDef;
	uint32				frameCount;

	// Third person camera
	bool				thirdPerson;
	byte				cameraTrans;

	// Prediction
	cgPredictionState_t	predicted;

	netFrame_t			frame;								// received from server
	netFrame_t			oldFrame;
	float				lerpFrac;							// between oldFrame and frame

	bool				attractLoop;

	//
	// Network
	//
	int					playerNum;

	bool				localServer;
	char				*serverMessage;
	char				*serverName;
	int					serverProtocol;
	int					protocolMinorVersion;
	int					connectCount;

	cgDownloadInfo_t	download;
	bool				acLoading;

	//
	// Config strings
	//
	char					configStrings[MAX_CFGSTRINGS][MAX_CFGSTRLEN];
	struct refMaterial_t	*imageCfgStrings[MAX_CS_IMAGES];
	struct refModel_t		*modelCfgDraw[MAX_CS_MODELS];
	struct cmBspModel_t		*modelCfgClip[MAX_CS_MODELS];
	struct sfx_t			*soundCfgStrings[MAX_CS_SOUNDS];

	//
	// Loading screen
	//
	bool				mapLoaded;
	bool				mapLoading;
	int					loadingMaxValues;
	int					loadingValue;

	char				loadingString[MAX_QPATH];
	char				loadFileName[MAX_QPATH];

	//
	// Menu
	//
	bool				menuOpen;

	//
	// HUD and inventory
	//
	vec2_t				hudScale;

	char				layout[1024];				// general 2D overlay
	int					inventory[MaxItems];

	//
	// Client info
	//
	int					maxClients;
	clientInfo_t		clientInfo[MAX_CS_CLIENTS];
	clientInfo_t		baseClientInfo;

	//
	// Enhanced protocol support
	//
	bool				strafeHack;

	//
	// Effects
	//
	float				goreScale; // 0.0-1.0
	float				smokeLingerScale; // 0.0-1.0


	// Bobbing
	float				xyspeed;
	float				oldBobTime;
	int					bobCycle;
	float				bobFracSin;
	bool				isOnGround;

	void Clear ()
	{
		netTime = netFrameTime = refreshTime = refreshFrameTime = 0;
		realTime = 0;
		frameCount = 0;
		mapLoaded = mapLoading = false;
		bonusAlpha = damageAlpha = 0;

		viewBlend = colorf(0, 0, 0, 0);
		memset (configStrings, 0, sizeof(configStrings));
		memset (imageCfgStrings, 0, sizeof(imageCfgStrings));
		memset (modelCfgDraw, 0, sizeof(modelCfgDraw));
		memset (modelCfgClip, 0, sizeof(modelCfgClip));
		memset (soundCfgStrings, 0, sizeof(soundCfgStrings));
	}
};

extern cgState_t	cg;

/*
=============================================================================

	PLAYER MOVEMENT

=============================================================================
*/

//
// pmove.c
// common between the client and server for consistancy
//
void	Pmove (pMoveNew_t *pMove, float airAcceleration);

//
// cg_predict.c
//
void	CG_CheckPredictionError ();
void	CG_BuildSolidList ();
void	CG_PMTrace (cmTrace_t *out, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, bool entities, bool bModels);
void	CG_Trace (cmTrace_t *out, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, bool entities, bool bModels, int ignore, int contentMask);
int		CG_PMPointContents (vec3_t point);
void	CG_PredictMovement ();
void	CG_ProjectSource (byte handedNess, vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result);

/*
=============================================================================

	SCREEN

=============================================================================
*/

//
// cg_screen.c
//

struct refMaterial_t	*CG_RegisterPic (char *name);

byte	palRed (int index);
byte	palGreen (int index);
byte	palBlue (int index);

float	palRedf (int index);
float	palGreenf (int index);
float	palBluef (int index);

void	CG_AddNetgraph ();
void	CG_DebugGraph (float value, int color);
void	CG_DrawDebugGraph ();

void	SCR_UpdatePING ();

void	SCR_ParseCenterPrint ();

void	SCR_Draw ();

//
// cg_view.c
//

void	V_RenderView (int realTime, float netFrameTime, float refreshFrameTime, float stereoSeparation, bool refreshPrepped);

void	V_Register ();
void	V_Unregister ();

/*
=============================================================================

	INVENTORY / HUD

=============================================================================
*/

//
// cg_hud.c
//

void	HUD_CopyLayout ();
void	HUD_DrawLayout ();
void	HUD_DrawStatusBar ();

//
// cg_inventory.c
//

void	Inv_ParseInventory ();
void	Inv_DrawInventory ();

/*
=============================================================================

	NEAREST LOCATION SUPPORT

=============================================================================
*/

void	CG_LocationInit ();
void	CG_LocationShutdown ();

void	CG_LoadLocations (char *mapName);

void	CG_Say_Preprocessor ();

/*
=============================================================================

	CONSOLE VARIABLES

=============================================================================
*/

extern cVar_t	*cg_advInfrared;
extern cVar_t	*cg_brassTime;
extern cVar_t	*cg_decals;
extern cVar_t	*cg_decalBurnLife;
extern cVar_t	*cg_decalFadeTime;
extern cVar_t	*cg_decalLife;
extern cVar_t	*cg_decalLOD;
extern cVar_t	*cg_decalMax;
extern cVar_t	*cg_mapEffects;
extern cVar_t	*cl_add_particles;
extern cVar_t	*cg_particleCulling;
extern cVar_t	*cg_particleGore;
extern cVar_t	*cg_particleMax;
extern cVar_t	*cg_particleShading;
extern cVar_t	*cg_particleSmokeLinger;
extern cVar_t	*cg_railCoreRed;
extern cVar_t	*cg_railCoreGreen;
extern cVar_t	*cg_railCoreBlue;
extern cVar_t	*cg_railSpiral;
extern cVar_t	*cg_railSpiralRed;
extern cVar_t	*cg_railSpiralGreen;
extern cVar_t	*cg_railSpiralBlue;
extern cVar_t	*cg_thirdPerson;
extern cVar_t	*cg_thirdPersonAngle;
extern cVar_t	*cg_thirdPersonClip;
extern cVar_t	*cg_thirdPersonDist;
extern cVar_t	*cg_simpleitems;

extern cVar_t	*cg_explorattle;
extern cVar_t	*cg_explorattle_scale;
extern cVar_t	*cl_footsteps;
extern cVar_t	*cl_gun;
extern cVar_t	*cl_noskins;
extern cVar_t	*cl_predict;
extern cVar_t	*cl_showmiss;
extern cVar_t	*cl_vwep;

extern cVar_t	*crosshair;

extern cVar_t	*gender_auto;
extern cVar_t	*gender;
extern cVar_t	*hand;
extern cVar_t	*skin;

extern cVar_t	*cl_testblend;
extern cVar_t	*cl_testentities;
extern cVar_t	*cl_testlights;
extern cVar_t	*cl_testparticles;

extern cVar_t	*r_hudScale;
extern cVar_t	*r_fontScale;

extern cVar_t	*crosshair;
extern cVar_t	*ch_alpha;
extern cVar_t	*ch_pulse;
extern cVar_t	*ch_scale;
extern cVar_t	*ch_red;
extern cVar_t	*ch_green;
extern cVar_t	*ch_blue;
extern cVar_t	*ch_xOffset;
extern cVar_t	*ch_yOffset;

extern cVar_t	*cl_showfps;
extern cVar_t	*cl_showping;
extern cVar_t	*cl_showtime;

extern cVar_t	*con_chatHud;
extern cVar_t	*con_chatHudLines;
extern cVar_t	*con_chatHudPosX;
extern cVar_t	*con_chatHudPosY;
extern cVar_t	*con_chatHudShadow;
extern cVar_t	*con_notifyfade;
extern cVar_t	*con_notifylarge;
extern cVar_t	*con_notifylines;
extern cVar_t	*con_notifytime;
extern cVar_t	*con_alpha;
extern cVar_t	*con_clock;
extern cVar_t	*con_drop;
extern cVar_t	*con_scroll;

extern cVar_t	*scr_conspeed;
extern cVar_t	*scr_centertime;
extern cVar_t	*scr_showpause;
extern cVar_t	*scr_hudalpha;

extern cVar_t	*scr_netgraph;
extern cVar_t	*scr_timegraph;
extern cVar_t	*scr_debuggraph;
extern cVar_t	*scr_graphheight;
extern cVar_t	*scr_graphscale;
extern cVar_t	*scr_graphshift;
extern cVar_t	*scr_graphalpha;

extern cVar_t	*viewsize;
extern cVar_t	*gl_polyblend;

extern cVar_t	*cg_paused;
extern cVar_t	*cg_timeDemo;

extern cVar_t	*cg_bobSpeed;
extern cVar_t	*cg_bobPitch;
extern cVar_t	*cg_bobYaw;
extern cVar_t	*cg_bobRoll;

/*
=============================================================================

	SUPPORTING FUNCTIONS

=============================================================================
*/

//
// cg_draw.c
//

void		CG_DrawModel (int x, int y, int w, int h, struct refModel_t *model, struct refMaterial_t *mat, vec3_t origin, vec3_t angles);

//
// cg_main.c
//

void		CG_SetRefConfig (refConfig_t *inConfig);

void		CG_UpdateCvars(const bool bForceUpdate = false);

void		CG_LoadMap (int playerNum, int serverProtocol, int protocolMinorVersion, bool attractLoop, bool strafeHack, refConfig_t *inConfig);

void		CG_Init ();
void		CG_Shutdown ();

// hud
void		HUD_LoadHuds ();
void		HUD_CloseHuds ();


//
// cg_muzzleflash.c
//

void		CG_ParseMuzzleFlash (entityState_t *ent, int eventID);
void		CG_ParseMuzzleFlash2 ();

//
// cg_players.c
//

void		CG_LoadClientinfo (clientInfo_t *ci, char *skin);

void		CG_StartSound (vec3_t origin, int entNum, EEntSndChannel entChannel, int soundNum, float volume, float attenuation, float timeOffset);
void		CG_FixUpGender ();

//
// cg_parse.c
//

void		CG_ParseClientinfo (int player);

void		CG_ParseConfigString (int num, char *str);

void		CG_StartServerMessage ();
void		CG_EndServerMessage (int realTime);
bool		CG_ParseServerMessage (int command);

// cg_item.cpp
enum
{
	ITEMBIT_SOUNDS		= 1,
	ITEMBIT_MODELS		= 2,
	ITEMBIT_PICS		= 4,
	
	ITEMBIT_MASK = ITEMBIT_SOUNDS | ITEMBIT_MODELS | ITEMBIT_PICS
};

void CG_ItemMediaInit (byte bits);

// Viewblend
void CG_VB_AddBlend (float r, float g, float b, float a);
void CG_VB_DrawViewBlends ();

/*
=============================================================================

	INTERFACES

=============================================================================
*/

//
// cg_loadscreen.c
//

void	CG_LoadingValues (int values);
void	CG_IncLoadingVal ();
void	CG_LoadingString (char *str);
void	CG_LoadingFilename (char *str);

void	CG_UpdateConnectInfo (char *serverName, char *serverMessage, int connectCount, char *dlFileName, int dlPercent, float bytesDownloaded, bool acLoading);
void	CG_DrawConnectScreen ();

#endif // __CGAME_LOCAL_H__
